﻿using System.Linq.Expressions;
using SqlSugar;
using WeDonekRpc.Helper;
using WeDonekRpc.SqlSugar;
using WeDonekRpc.SqlSugar.Repository;

namespace Shop.Repository.lmpl
{
    internal class ShopBaseRepository<T, IdentityId> : BasicRepository<T>, IShopBaseRepository<T, IdentityId> where T : class, new()
    {
        private readonly string _prefix;
        public ShopBaseRepository ( ISqlClientFactory factory ) : base(factory, "shop")
        {
            this._prefix = typeof(T).Name.ToLower();
            if ( this._prefix.StartsWith("db") )
            {
                this._prefix = this._prefix.Substring(2);
            }
            if ( this._prefix.EndsWith("repository") )
            {
                this._prefix = this._prefix.Substring(0, this._prefix.Length - 10);
            }
        }
        
        public Result[] GetTops<Result> ( int top, string orderBy ) where Result : class, new()
        {
            return base.Queryable.OrderBy(orderBy).Select<Result>().Take(top).ToArray();
        }
        public Result[] GetTops<Result> ( Expression<Func<T, bool>> filter, int top, string orderBy ) where Result : class, new()
        {
            return base.Queryable.Where(filter).OrderBy(orderBy).Select<Result>().Take(top).ToArray();
        }
        public Result[] GetTops<Result> ( Expression<Func<T, bool>> filter, Expression<Func<T, Result>> selector, int top, string orderBy )
        {
            return base.Queryable.Where(filter).OrderBy(orderBy).Select<Result>(selector).Take(top).ToArray();
        }
        public Result[] GetTops<Result> ( int top, string sortBy, OrderByType type ) where Result : class, new()
        {
            return base.Queryable.OrderByPropertyName(sortBy, type).Select<Result>().Take(top).ToArray();
        }
        public virtual void Delete ( IdentityId id )
        {
            if ( !base.DeleteByKey(id) )
            {
                throw new ErrorException("shop." + this._prefix + ".delete.fail");
            }
        }
        public virtual void Delete ( IdentityId[] ids )
        {
            if ( !base.DeleteByKey(ids) )
            {
                throw new ErrorException("shop." + this._prefix + ".delete.fail");
            }
        }
        public Result Get<Result> ( IdentityId id, Expression<Func<T, Result>> selector )
        {
            Result res = base.GetById<IdentityId, Result>(id, selector);
            if ( res == null )
            {
                throw new ErrorException("shop." + this._prefix + ".not.find");
            }
            return res;
        }
        public Result Get<Result> ( IdentityId id ) where Result : class
        {
            Result res = base.GetById<IdentityId, Result>(id);
            if ( res == null )
            {
                throw new ErrorException("shop." + this._prefix + ".not.find");
            }
            return res;
        }
        public T Find ( IdentityId id )
        {
            return base.GetById<IdentityId>(id);
        }
        public T Get ( IdentityId id )
        {
            T result = base.GetById<IdentityId>(id);
            if ( result == null )
            {
                throw new ErrorException("shop." + this._prefix + ".not.find");
            }
            return result;
        }

        public T[] Gets ( IdentityId[] ids )
        {
            T[] result = this.GetsById<IdentityId>(ids);
            if ( result.IsNull() )
            {
                throw new ErrorException("shop." + this._prefix + ".not.find");
            }
            return result;
        }
        public Result[] Gets<Result> ( IdentityId[] ids ) where Result : class
        {
            Result[] result = this.GetsById<IdentityId, Result>(ids);
            if ( result.IsNull() )
            {
                throw new ErrorException("shop." + this._prefix + ".not.find");
            }
            return result;
        }

        public Result[] Gets<Result> ( IdentityId[] ids, Expression<Func<T, Result>> selector )
        {
            Result[] result = base.GetsById<IdentityId, Result>(ids, selector);
            if ( result.IsNull() )
            {
                throw new ErrorException("shop." + this._prefix + ".not.find");
            }
            return result;
        }

        public Result[] GetAll<Result> ( string orderBy ) where Result : class, new()
        {
            return base.Queryable.OrderBy(orderBy).Select<Result>().ToArray();
        }
    }
}
